var GameEngine = function(settings)
{
thisObj = this;

this.reporter = new Reporter(thisObj);
this.creator		= settings.creator;
this.timePerFrameWanted = settings.timePerFrameWanted;

this.gamePlay			= settings.gamePlay;			// Rules of the current game	
this.squareWidth 		= settings.squareWidth;			// Width of a square in a pattern
this.squareHeight 		= settings.squareHeight;		// Height of a square in a pattern

this.patternColumns		= settings.patternColumns;
this.patternRows		= settings.patternRows;
this.colorPalette		= [
[15,240,20],
[255,7,5],
[42,15,255],
[8,5,255],
[28,15,255],
[28,28,68],
[187,187,187],
[7,7,157],
[157,7,7],
[7,157,7]
];
this.randomColor = function(string){
	if(string)
	{
	var returnArr = this.colorPalette[Math.floor(Math.random()*(this.colorPalette.length))];
	return "rgb("+returnArr[0]+","+returnArr[1]+","+returnArr[2]+"); ";
	}
	else
	{
	return this.colorPalette[Math.floor(Math.random()*(this.colorPalette.length))];
	}
}
var darkenColor = function(color){
	var returnColor = [];
	returnColor[0] = Math.floor(color[0]*0.7);
	returnColor[1] = Math.floor(color[1]*0.7);
	returnColor[2] = Math.floor(color[2]*0.7);
return returnColor;
}
this.color = function(string,id){
	if(string)
	{
	var returnArr = this.colorPalette[id];
	return "rgb("+returnArr[0]+","+returnArr[1]+","+returnArr[2]+"); ";
	}
	else
	{
	return this.colorPalette[id];
	}
}
this.spacing = 40;
this.patternPile = [];
this.patternPileReserve = [];
this.setEndToMatch = 1;

var pattern;
var newPatternXCoord;
var patternPath;
patternPath = new PatternPath({patternRows:this.patternRows,patternColumns:this.patternColumns});
var setPatternColorPair 
	for(var i=0;i<this.patternRows;i++)
	{
		for(var j=0;j<this.patternColumns;j++)
		{
			if( (j+i*this.patternColumns) >= ((this.patternColumns)*(this.patternRows)-this.gamePlay.nBack) )
			{
			this.setEndToMatch=0;
			}
    	newPatternCoord = patternPath.giveCoordinates( j+i*this.patternColumns );
		pattern = new Pattern(this.gamePlay.patternSize,this.gamePlay.patternOdds,thisObj);
		setPatternColorPair = this.randomColor()
		pattern.negative = new PatternPole("negative",0,0,0,this.squareWidth,this.squareHeight,setPatternColorPair,pattern,0,newPatternCoord[0],newPatternCoord[1],this.spacing,this.spacing);
		pattern.positive = new PatternPole("positive",0,0,this.setEndToMatch*Math.floor(Math.random()*4),this.squareWidth,this.squareHeight,darkenColor(setPatternColorPair),pattern,0,(this.patternColumns-1),(this.patternRows-1),this.spacing,this.spacing);
		this.patternPile.push( pattern );
		}
	}
	newPatternXCoord = patternPath.giveCoordinates(0)[0];
      	if(newPatternXCoord>0){
      	newPatternXCoord++;
      	}
      	else
      	{
      	newPatternXCoord--;
      	}
	for(var i=0;i<this.gamePlay.turns;i++)
	{
			setPatternColorPair = this.randomColor()
			pattern = new Pattern(this.gamePlay.patternSize,this.gamePlay.patternOdds,thisObj);
			pattern.negative = new PatternPole("negative",0,0,0,this.squareWidth,this.squareHeight,setPatternColorPair,pattern,0,newPatternXCoord,0,this.spacing,this.spacing);
			pattern.positive = new PatternPole("positive",0,0,Math.floor(Math.random()*4),this.squareWidth,this.squareHeight,darkenColor(setPatternColorPair),pattern,0, (this.patternColumns-1),(this.patternRows-1),this.spacing,this.spacing);
			this.patternPileReserve.push( pattern );
	}
	
	
	
		
	this.creator.canvas.width = this.patternColumns*(6+this.squareWidth*(this.gamePlay.patternSize+1))+this.spacing*2-(this.squareWidth+6);
	this.creator.canvas.height = this.patternRows*(6+this.squareHeight*(this.gamePlay.patternSize+1))+this.spacing*2-(this.squareHeight+6);
	$(this.creator.canvas).css({"border":"1px solid grey"});
this.timeNow;
this.timeThen;
this.timePassed = 0;
this.startTime;
this.offSet = 0;
// Number of frames used to calculate average framerate
var statShowCount = 0;
var makeNextFrame = true;

var checkCorrect = 0; // Gives correct while turnsWent >= level
var correct;

var startPaintAnimCounter = 0;
var thisObj;

	this.startPaint = function(){
		if (startPaintAnimCounter==0)
		{
		thisObj=this;
		this.creator.context.fillStyle = "rgb(160,160,160)";
		this.creator.context.fillRect(0,0,this.creator.canvas.width,this.creator.canvas.height);
		this.reporter.reportStartGame();
		setTimeout(function(thisObj) { thisObj.startPaint(); }, 30, this);
		}
		else if(startPaintAnimCounter<99 && this.patternPile != null) // Patternpile ==null is a measure used to see if game has been ended prematurely.
		{
		this.creator.context.fillStyle = "rgb(10,"+Math.floor(200*startPaintAnimCounter)+",20)";
		this.creator.context.fillRect(0,(this.creator.canvas.height-20),this.creator.canvas.width*(startPaintAnimCounter/100),20);	
		setTimeout(function(thisObj) { thisObj.startPaint(); }, 30, this);
		}
		else if(this.patternPile != null)
		{
		setTimeout(function(thisObj) { if(thisObj.patternPile!=null){thisObj.paintStep();} }, 35, this);
		}
	startPaintAnimCounter++;
	}
	
	this.paintStep = function(){
	this.startTime = new Date();
	this.timeNow = new Date();
	this.timeThen = new Date();
	this.gamePlay.startTimer();	
	thisObj = this;
	this.frameTimer = setInterval(function(thisObj) { thisObj.paint(); }, this.timePerFrameWanted, this);
	}
	
	this.paint = function()
	{
	timeThen = new Date();
	var correct = false;
	this.creator.context.clearRect(0,0,this.creator.canvas.width,this.creator.canvas.height);
	this.creator.context.beginPath();
	
		for(var i = 0; i<this.patternPile.length;i++)
		{
			if(i < (this.patternPile.length-this.gamePlay.nBack) )
			{
			this.patternPile[i].negative.draw(this.creator.context,0,0,0);
			}
		}
	i = this.patternPile.length-1;
		
	stepPosition = this.patternPile[i].positive.angle/90;
		if(this.gamePlay.turnsWent>=this.gamePlay.nBack)
		{
			if(stepPosition!=this.patternPile[i].positive.stepToAngle)
			{
			this.patternPile[i].positive.draw(this.creator.context,15*this.patternPile[i].positive.rotationDirection,0,0);
			}
			else
			{
			this.patternPile[i].positive.draw(this.creator.context,0,0,0);
			}
		checkCorrect = this.patternPile[i].positive.stepToAngle-this.patternPile[i].negative.stepToAngle;
		}
		if(this.patternPile[i].rotationsCorrect[checkCorrect]){
		correct = true;
		}
		for(var k=0;k<this.patternPile[i].rotationsCorrectWarned.length;k++)
		{
			if(checkCorrect===k)
			{
			this.patternPile[i].rotationsCorrectWarned[k]=true;
			}
			else if(this.patternPile[i].rotationsCorrectWarned[k])
			{
			this.patternPile[i].rotationsCorrectWarned[k]=false;
			}
		}

		if(this.gamePlay.timePerTurn<=this.gamePlay.timeUsedPerTurn)
		{
			if(this.gamePlay.nBack<this.gamePlay.turnsWent+1)
			{
			this.gamePlay.mistakes++;
			correct=true;
			}
		this.patternPile[this.patternPile.length-1].positive.continueSet=true;
		}
		
		if(this.patternPile[this.patternPile.length-1].positive.continueSet)
		{
		this.patternPile[this.patternPile.length-1].positive.continueSet = false;
			if(correct)
			{
			this.gamePlay.timeUsedPerTurn=0;			
      		this.patternPile.pop();
			this.patternPile.unshift( this.patternPileReserve.pop() );
      			for(var x in this.patternPile)
      			{
	      		var coords = patternPath.giveCoordinates(x);
	      		this.patternPile[x].negative.stepToX = coords[0];
	      		this.patternPile[x].negative.stepToY = coords[1];
      			}
      		}
	    makeNextFrame=this.gamePlay.moveTurn(correct);      			      		
		}

	indicatorRatio = 1-this.gamePlay.timeUsedPerTurn/this.gamePlay.timePerTurn;

	this.creator.context.fillStyle = this.color(true,0);
	this.creator.context.fillRect(0,(this.creator.canvas.height-20),this.creator.canvas.width*indicatorRatio,20);
	this.creator.context.fillStyle = this.color(true,1);
	this.creator.context.fillRect(0,0,(this.creator.canvas.width*(this.gamePlay.turnsWent+1-indicatorRatio)/this.gamePlay.turns),20);

	this.timeNow = new Date();										// Time now
	this.timePassed = this.timeNow - this.timeThen;					// Time used per frame
	this.timeThen = new Date();
	
	this.gamePlay.timeUsedPerTurn+=this.timePassed;
	
		this.offSet += (this.timePerFrameWanted-this.timePassed);
		
		if(!makeNextFrame){

			this.reporter.reportEndGame();

		this.cleanUp();
		this.creator.restart();		
		}

/*
		if(statShowCount>10|!makeNextFrame)
		{
		document.getElementById("timer2").value="Timeprframe"+this.timePassed+"ms\nFramerate:"+Math.round(10000/this.timePassed)/10+"fps\nOffset:"+this.offSet+"ms"+"\nTurns passed:"+(this.gamePlay.turnsWent-this.gamePlay.nBack)+"/"+(this.gamePlay.turns-this.gamePlay.nBack)+"\nMistakes:"+this.gamePlay.mistakes+"\nN-Back:"+this.gamePlay.nBack+"\nTime used:"+(this.gamePlay.timeSpent/1000)+"sek\n"+"\n"+(new Date()-timeThen)+"-"+this.timePerFrameWanted;
		statShowCount=0;
		}
		else
		{
		statShowCount++;
		}
*/
	}
	
	this.cleanUp = function(){
	$("#newGame").get(0).disabled = false;
	$("#resetScores").get(0).disabled = false;
	clearTimeout(this.frameTimer);
	this.frameTimer = null;
	this.patternPile = null;
	// this.gamePlay = null;
	this.gamePlay.clean();
	$("html").unbind("keypress");

			$("html").keypress(function(event) {
				if (event.keyCode == '32' || event.keyCode == '38'|| event.keyCode == '40') {
				thisObj.creator.createNewGame();
				return false;
   				}   				
			});

	}
}